import numpy as np


Saaty = {
    1: 0,
    2: 0,
    3: 0.58,
    4: 0.90,
    5: 1.12,
    6: 1.24,
    7: 1.32,
    8: 1.41,
    9: 1.45,
    10: 1.49,
    11: 1.51
}
Standard = 0.1


# 进行（行数-1）次的操作
"""
只需输入C1：C2，C1：C3...C1:C5,
              C2:C3...C2:C5的上对角矩阵
其他数据如对角线 下对角由程序生成
"""
def generate_matrix(row):
    temp_list = []
    for i in range(row - 1):
        row_temp_list = ("1.0 " + input("请输入上对角第%d行（除对角线）的数据，以空格分开" % (i + 1))).split()
        while len(row_temp_list) != row - i:
            print("=======输入的项数有误， 请重新输入=======")
            row_temp_list = ("1.0 " + input("请输入上对角第%d行（除对角线）的数据，以空格分开" % (i + 1))).split()
            # 对输入的每一项进行格式转换
        row_temp_list = list(map(lambda x: float(eval(x)), row_temp_list))
        temp_list.append(row_temp_list)
    temp_list.append([1.0])

    matrix = [temp_list[0]]
    for i in range(1, row):
        row_temp_list = []
        for x in range(i):
            var = 1.0 / temp_list[x][i - x]
            row_temp_list.append(var)
        row_temp_list = row_temp_list + temp_list[i]
        matrix.append(row_temp_list)
    print("生成的矩阵\n")
    print(matrix)
    return matrix


# 得到归一化权向量
def get_weight_matrix(matrix):
    lambd_max = []
    lambd, feature_vector = np.linalg.eig(matrix)
    lambd = lambd.T
    feature_vector = feature_vector.T


    # 求得最大特征值对应的特征向量
    lambd_max = max(lambd)
    index = np.where(lambd.max() == lambd_max)[0][0]

    weight_vector = feature_vector[index]
    normal_weight_vector = np.abs(weight_vector / np.sum(weight_vector))


    matrix_info = {
        'feature_vector': feature_vector,
        'lambd_max': lambd_max,
        'normal_weight_vector': normal_weight_vector
    }
    return matrix_info


# 验证一致性
def validate(lambd_max, rows):
    CI = (lambd_max - rows) / (rows - 1)
    CR = CI / Saaty[rows]
    if CR < Standard:
        return True
    else:
        return False


rows = int(input("请输入准则层的因素个数"))
destinies = int(input("请输入目标层个数"))

temp_list = []


while True:
    # 生成成对比较阵
    # matrix = generate_matrix(rows)
    # 先用定义好的矩阵测试
    matrix = [[1, 0.5, 4, 3, 3],
              [2, 1, 7, 5, 5],
              [0.25, 1/7, 1, 0.5, 1/3],
              [1/3, 1/5, 2, 1, 1],
              [1/3, 1/5, 3, 1, 1]]
    matrix = np.array(matrix, dtype=float)
    print(matrix)
    if np.linalg.matrix_rank(matrix) != 1:
        weight_matrix = get_weight_matrix(matrix)
        weight = weight_matrix['normal_weight_vector']
    else:
        weight = matrix[:, 0]
        weight = weight/np.sum(weight)
    print("归一化后的权向量")
    print(weight)
    lambd_max = weight_matrix['lambd_max']

    if not validate(lambd_max, rows):
        print("====不能通过一致性检验， 请重新输入矩阵====")

    else:
        print("====通过一致性检验====")
        break


#得到方案层组合权向量
plan_weight_matrixes = []

print("====定义组合权向量====")
for i in range(1, rows+1):
    while True:
        plan_matrix = generate_matrix(destinies)
        plan_matrix = np.array(plan_matrix, dtype=float)
        # 矩阵的秩不为1，则正常求解(这里最开始忽略了，没做判断，测试时在秩为1时计算出错)
        if np.linalg.matrix_rank(plan_matrix) != 1:
            weight_matrix = get_weight_matrix(plan_matrix)
            plan_weight = weight_matrix['normal_weight_vector']
            lambd_max = weight_matrix['lambd_max']
            # feature_vec = weight_matrix['feature_vector']
        # 秩为1，则任选一列作为特征向量，再求权向量
        else:
            feature_vec = plan_matrix[:, 0]
            plan_weight = feature_vec/np.sum(feature_vec)
        if validate(lambd_max, destinies):
            print("=====通过一致性检验======\n归一化后的权向量为")
            print(plan_weight)
            plan_weight_matrixes.append(plan_weight)
            break
        else:
            print("====不能通过一致性检验， 请重新输入矩阵====")
W = np.array(plan_weight_matrixes)

result = np.dot(W.T, weight)
print("=====目标层的各项权重=====")
print(result)
result_sorted = np.sort(result)  # 对结果列表进行排序
print(np.max(result))
print("第{}个选项权重最大， 权重值为{}".format(np.where(result_sorted[-1] == result)[0][0]+1, np.max(result)))
